﻿//Copyright (C) 2009  Jaco (ScionBot.com)

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Scion.Library.Advanced;

namespace Scion.Library.Underlying
{
    /// <summary>
    /// Basic colour functions.
    /// </summary>
    public class Colour : Determine
    {
        /// <summary>
        /// Find a pixel with a tolerance.
        /// </summary>
        /// <param name="bmp">The bitmap to find the pixel in.</param>
        /// <param name="rect">The bounds to search in (X, Y, X2, Y2).</param>
        /// <param name="c">The colour to search for.</param>
        /// <param name="tolerance">The tolerance of the pixel.</param>
        /// <returns>Returns the point of the first found pixel.</returns>
        public static Point FindColour(BufferedImage bmp, Rectangle rect, Color c, int tolerance)
        {
            int r = c.R; int g = c.G; int b = c.B;
            for (int Y = rect.Y; Y < (rect.Height + 1); Y++)
            {
                for (int X = rect.X; X < (rect.Width + 1); X++)
                {
                    int tempR; int tempG; int tempB;
                    bmp.GetPixel(X, Y, out tempR, out tempG, out tempB);
                    if (IsTolerance(tempR, tempG, tempB, r, g, b, tolerance))
                        return new Point(X, Y);
                }
            }
            return new Point(-1, -1);
        }

        /// <summary>
        /// Find a colour in a spiral on the RS canvas.
        /// </summary>
        /// <param name="bmp">The bitmap to search in.</param>
        /// <param name="rect">The bounds to find the colour in.</param>
        /// <param name="start">The start location of the spiral.</param>
        /// <param name="c">The colour to find.</param>
        /// <param name="tolerance">The tolerance of the pixel to find.</param>
        /// <returns>Returns the point found.</returns>
        public static Point FindColourSpiral(BufferedImage bmp, Rectangle rect, Point start, Color c, int tolerance)
        {
            int startX = start.X;
            int startY = start.Y;
            int startR; int startG; int startB;
            int cR = c.R; int cG = c.G; int cB = c.B;
            bmp.GetPixel(startX, startY, out startR, out startG, out startB);
            if (IsTolerance(startR, startG, startB, cR, cG, cB, tolerance))
                return start;
            int incrementX = startX + 1;
            int incrementY = startY + 1;
            int direction = 0; int length = 3;
            while ((incrementX < (rect.Width + 1)) || (incrementY < (rect.Height + 1) || (incrementX > -1) || (incrementY > -1)))
            {
                for (int go = 1; go < 5; go++)
                {
                    for (int i = 1; i < (length + 1); i++)
                    {
                        switch (direction)
                        {
                            case 0:
                                incrementY--;
                                break;
                            case 1:
                                incrementX--;
                                break;
                            case 2:
                                incrementY++;
                                break;
                            case 3:
                                incrementX++;
                                break;
                        }
                        if ((incrementX == -1) || (incrementY == -1))
                            return new Point(-1, -1);
                        int foundR; int foundG; int foundB;
                        bmp.GetPixel(incrementX, incrementY, out foundR, out foundG, out foundB);
                        if (IsTolerance(foundR, foundG, foundB, cR, cG, cB, tolerance))
                            return new Point(incrementX, incrementY);
                    }
                    if (direction == 3)
                        direction = 0;
                    else
                        direction++;
                }
                incrementX++;
                incrementY++;
                length = length + 2;
            }
            return new Point(-1, -1);
        }

        /// <summary>
        /// Find a bitmap image.
        /// </summary>
        /// <param name="bmp">The bitmap to search in.</param>
        /// <param name="bitmapToFind">The bitmap to find.</param>
        /// <param name="rect">The bounds to search in (X, Y, X2, Y2).</param>
        /// <param name="mask">Skipped masked pixels with the colour Cyan (0,255,255).</param>
        /// <param name="tolerance">The tolerance of each pixel.</param>
        /// <returns>Returns the point of the found location.</returns>
        public static Point FindBitmap(BufferedImage bmp, BufferedImage bitmapToFind, Rectangle rect, bool mask, int tolerance)
        {
            int maskR = 0; int maskG = 255; int maskB = 255;
            int cR; int cG; int cB;
            bitmapToFind.GetPixel(0, 0, out cR, out cG, out cB);
            for (int Y = rect.Y; Y < (rect.Height + 1); Y++)
            {
                for (int X = rect.X; X < (rect.Width + 1); X++)
                {
                    int currentR; int currentG; int currentB;
                    bmp.GetPixel(X, Y, out currentR, out currentG, out currentB);
                    if (IsTolerance(cR, cG, cB, currentR, currentG, currentB, tolerance))
                    {
                        int xSave = X;
                        int ySave = Y;
                        for (int Y2 = 0; Y2 < bitmapToFind.imageHeight; Y2++)
                        {
                            for (int X2 = 0; X2 < bitmapToFind.imageWidth; X2++)
                            {
                                int checkR; int checkG; int checkB;
                                int check2R; int check2G; int check2B;
                                bitmapToFind.GetPixel(X2, Y2, out checkR, out checkG, out checkB);
                                bmp.GetPixel(X2 + xSave, Y2 + ySave, out check2R, out check2G, out check2B);
                                if (mask && IsMatch(checkR, checkG, checkB, maskR, maskG, maskB))
                                    goto End;
                                else if (!IsTolerance(checkR, checkG, checkB, check2R, check2G, check2B, tolerance))
                                    goto NextPixel;
                            End:
                                continue;
                            }
                        }
                        return new Point(xSave, ySave);
                    }
                NextPixel:
                    continue;
                }
            }
            return new Point(-1, -1);
        }
    }
}
